package club.lemos.textdrawer;


import lombok.Data;
import lombok.extern.java.Log;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

@Log
@Data
public class TextDrawer {

    // 宽度
    private static final int DEFAULT_WIDTH = 450;
    // 高度
    private static final int DEFAULT_HEIGHT = 400;
    // 行间距
    private static final int DEFAULT_LINE_HEIGHT = 30;

    // 模板宽度
    private int bgWidth = DEFAULT_WIDTH;

    // 模板高度
    private int bgHeight = DEFAULT_HEIGHT;

    // 模板行间距
    private int lineHeight = DEFAULT_LINE_HEIGHT;

    //文字距离下划线高度
    private int underlinePaddingBottom = 25;

    //下划线下沉高度
    private int underlineLandingHeight = 8;

    // 默认字体
    private Font defaultFont = null;

    private Font underlineFont = null;

    private Color defaultColor = Color.black;

    private final BufferedImage image;

    private final Graphics2D graphic;

    private int currentX = 0;
    private int currentY = 0;

    private int paddingLeft = 30;

    private int paddingRight = 30;

    public TextDrawer(BufferedImage image) {
        this.image = image;
        this.graphic = image.createGraphics();
        // 消除锯齿
        this.graphic.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        this.graphic.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    public static TextDrawer init() {
        // 1.创建空白图片
        BufferedImage image = new BufferedImage(
                DEFAULT_WIDTH, DEFAULT_HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 2.获取图片画笔
        Graphics graphic = image.getGraphics();
        // 3.设置画笔颜色
        graphic.setColor(Color.white);
        // 4.绘制矩形背景
        graphic.fillRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
        // 5.绘制矩形边框
        graphic.setColor(Color.lightGray);
        graphic.drawRect(0, 0, DEFAULT_WIDTH - 1, DEFAULT_HEIGHT - 1);
        return new TextDrawer(image);
    }

    //空模板，可设置间距，字体，字体行高
    public static TextDrawer init(int paddingLeft, int paddingRight,
                                  Font defaultFont,
                                  int lineHeight) {
        TextDrawer imageDrawer = init();
        imageDrawer.setPaddingLeft(paddingLeft);
        imageDrawer.setPaddingRight(paddingRight);
        imageDrawer.setDefaultFont(defaultFont);
        imageDrawer.setLineHeight(lineHeight);
        return imageDrawer;
    }

    //输入流模板
    public static TextDrawer init(InputStream templateInputStream,
                                  int paddingLeft, int paddingRight,
                                  Font defaultFont,
                                  int lineHeight) throws IOException {
        BufferedImage image = ImageIO.read(templateInputStream);
        return init(image, paddingLeft, paddingRight, defaultFont, lineHeight);
    }

    //文件模板
    public static TextDrawer init(File templateFile,
                                  int paddingLeft, int paddingRight,
                                  Font defaultFont,
                                  int lineHeight) throws IOException {
        BufferedImage image = ImageIO.read(templateFile);
        return init(image, paddingLeft, paddingRight, defaultFont, lineHeight);
    }

    public static TextDrawer init(BufferedImage image,
                                  int paddingLeft, int paddingRight,
                                  Font defaultFont,
                                  int lineHeight) throws IOException {
        TextDrawer imageDrawer = new TextDrawer(image);
        imageDrawer.setBgWidth(image.getWidth());
        imageDrawer.setBgHeight(image.getHeight());
        imageDrawer.setPaddingLeft(paddingLeft);
        imageDrawer.setPaddingRight(paddingRight);
        imageDrawer.setDefaultFont(defaultFont);
        imageDrawer.setLineHeight(lineHeight);
        return imageDrawer;
    }

    public static TextDrawer init(BufferedImage image,
                                  int bgWidth, int bgHeight,
                                  int paddingLeft, int paddingRight,
                                  Font defaultFont,
                                  int lineHeight
    ) throws IOException {
        TextDrawer imageDrawer = new TextDrawer(image);
        imageDrawer.setBgWidth(bgWidth);
        imageDrawer.setBgHeight(bgHeight);
        imageDrawer.setPaddingLeft(paddingLeft);
        imageDrawer.setPaddingRight(paddingRight);
        imageDrawer.setDefaultFont(defaultFont);
        imageDrawer.setLineHeight(lineHeight);
        return imageDrawer;
    }

    public void output(File outputFile) throws IOException {
        try (OutputStream os = new FileOutputStream(outputFile)) {
            ImageIO.write(this.image, "JPG", os);
            log.info("已完成: {}" + outputFile.getAbsolutePath());
        }
    }

    public BufferedImage output() {
        return this.image;
    }

    public void show() {
        JFrame jFrame = new JFrame();
        jFrame.setTitle("图片预览");
        jFrame.setSize(1300, 800);
        ImagePanel imagePanel = new ImagePanel(this.image);
        jFrame.add(imagePanel);
        // 居中显示
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }

    public TextDrawer padding(int paddingLeft, int paddingRight) {
        this.setPaddingLeft(paddingLeft);
        this.setPaddingRight(paddingRight);
        return this;
    }

    public TextDrawer lineHeight(int lineHeight) {
        this.setLineHeight(lineHeight);
        return this;
    }

    public TextDrawer underlinePaddingBottom(int underlineBottomTop) {
        this.setUnderlinePaddingBottom(underlineBottomTop);
        return this;
    }

    public TextDrawer defaultFont(Font font) {
        this.setDefaultFont(font);
        return this;
    }

    public TextDrawer defaultColor(Color color) {
        this.setDefaultColor(color);
        return this;
    }

    public TextDrawer underlineFont(Font font) {
        this.setUnderlineFont(font);
        return this;
    }

    /**
     * 画图
     *
     * @throws IOException 异常
     */
    public TextDrawer draw(String s) throws IOException {
        int x = this.currentX;
        int y = this.currentY;
        if (y < lineHeight) {
            y = lineHeight;
        }
        return draw(s, x, y, null);
    }

    public TextDrawer draw(boolean ok, ImageText text) throws IOException {
        if (ok) {
            this.draw(text);
        }
        return this;
    }

    /**
     * 画图
     *
     * @param text 文字对象
     */
    public TextDrawer draw(ImageText text) throws IOException {
        Integer x = text.getX();
        if (x == null) {
            x = this.currentX;
        }
        Integer y = text.getY();
        if (y == null) {
            y = this.currentY;
            if (y < lineHeight) {
                y = lineHeight;
            } else {
                if (text.isNextLine()) {
                    y += lineHeight;
                }
            }
        }
        return draw(text.getText(), x, y, text.getTips());
    }

    public TextDrawer draw(ImageCenterText text) throws IOException {
        Integer x1 = text.getX1();
        Integer x2 = text.getX2();
        Integer y = text.getY();
        if (y == null) {
            y = this.currentY;
            if (y < lineHeight) {
                y = lineHeight;
            }
        }
        String str = text.getText();
        FontMetrics fontMetrics = graphic.getFontMetrics();
        int strWidth = fontMetrics.stringWidth(str);
        int x = (x1 + x2 - strWidth) / 2;
        return draw(str, x, y, text.getTips());
    }

    /**
     * 画图
     *
     * @param s 字符串
     * @param x 横坐标位置
     * @param y 纵坐标位置
     */
    public TextDrawer draw(String s, int x, int y, java.util.List<TextTip> textTips) throws IOException {
        int currX = x;
        int textHeight = 0;
        if (s != null && s.length() > 0) {
            //记录当前字符的横坐标位置
            int size = s.length();//每个字符串数组元素的长度
            for (int num = 0; num < size; num++) {
                boolean isCurrUnderline = false;
                String schar = s.charAt(num) + "";
                // 设置颜色
                graphic.setColor(this.defaultColor);
                // 设置字体大小，字体粗细
                if (defaultFont != null) {
                    graphic.setFont(defaultFont);
                } else {
                    graphic.setFont(new Font(null, Font.PLAIN, 30));
                }
                if (textTips != null) {
                    for (TextTip textTip : textTips) {
                        if (textTip.isHit(num)) {
                            graphic.setColor(textTip.getColor());
                            // 设置字体大小，字体粗细
                            if (textTip.getFont() != null) {
                                graphic.setFont(textTip.getFont());
                            } else {
                                graphic.setFont(this.getDefaultFont());
                            }
                            // 设置下划线
                            if (textTip.isUnderline()) {
                                isCurrUnderline = true;
                                Font underlineFont = this.getUnderlineFont();
                                if (underlineFont != null) {
                                    graphic.setFont(this.getUnderlineFont());
                                }
                            }
                            // 设置修饰属性
                            if (textTip.getAttributes() != null) {
                                graphic.setFont(graphic.getFont().deriveFont(textTip.getAttributes()));
                            }
                        }
                    }
                }
                FontMetrics fontMetrics = graphic.getFontMetrics();
                if (currX + fontMetrics.stringWidth(schar) > bgWidth - paddingRight) {
                    //每一行的前后都要留有一定空白，横坐标已经超出长度，需要折行
                    textHeight = textHeight + 1;
                    currX = paddingLeft;
                }
                // 画字符
                if (isCurrUnderline) {
                    graphic.drawString(schar, currX, y - this.underlinePaddingBottom + textHeight * lineHeight);
                    //带粗细的下划线
                    graphic.setStroke(new BasicStroke(5));
                    graphic.drawLine(currX, y + this.underlineLandingHeight + textHeight * lineHeight,
                            currX + fontMetrics.stringWidth(schar), y + this.underlineLandingHeight + textHeight * lineHeight);
                } else {
                    graphic.drawString(schar, currX, y + textHeight * lineHeight);
                }
                // 横坐标
                currX = currX + fontMetrics.stringWidth(schar);
                this.currentX = currX;
            }
        }
        // 纵坐标
        this.currentY = y + textHeight * lineHeight;
        return this;
    }

    public static void main(String[] args) throws IOException {
        BufferedImage bgImg = new BufferedImage(2400, 1400, BufferedImage.TYPE_INT_RGB);
        TextDrawer
                .init(bgImg, 50, 50, new Font(null, Font.PLAIN, 150), 306)
                .defaultColor(new Color(73, 73, 73))
                .padding(10, 10)
                .draw(ImageCenterText.text("你好，")
                        .position(0, 500, 400)
                        .tip(TextTip.range(0, 1).color(Color.ORANGE)))
                .draw(ImageText.text("我的爱人").tip(TextTip.range().color(Color.RED)))
                .draw(ImageText.text("眼睛是心灵的窗户").padding(4).underline())
                .draw(ImageText.nextLine())
                .draw(true, ImageText.text("明天再见").positionX(200))
                .show();
//                .output(new File("C:\\tmp\\abc", "d.jpg"));
    }

}
